﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using System.Web.Services.Protocols;
using System.Diagnostics;

namespace Boomerang.Common.Crm
{
    public class CrmDataSource
    {
        CrmConnection connection;
        QueryByAttribute queryPending;
        QueryByAttribute queryContact;

        public CrmDataSource(CrmConnection connection)
        {
            this.connection = connection;

            //Setup the Pending query
            queryPending = new QueryByAttribute();
            queryPending.EntityName = "tmc_sms";
            queryPending.ColumnSet = new ColumnSet(CrmSms.Columns);
            queryPending.Attributes = new string[] { "statuscode" };
            queryPending.Values = new object[] { (int)CrmSmsDeliveryStatus.Pending };

            //Setup the Contact query
            queryContact = new QueryByAttribute();
            queryContact.EntityName = "contact";
            queryContact.ColumnSet = new ColumnSet(new string[] { "contactid" });
            queryContact.Attributes = new string[] { "mobilephone" };
            queryContact.Values = new object[] { "" };
        }

        public List<BusinessEntity> RetrievePendingSms()
        {
            //Retrieve pending SMS from CRM
            RetrieveMultipleRequest request = new RetrieveMultipleRequest();
            request.Query = queryPending;
            request.ReturnDynamicEntities = true;
            try
            {
                RetrieveMultipleResponse response = (RetrieveMultipleResponse)connection.CrmService.Execute(request);
                return response.BusinessEntityCollection.BusinessEntities;
            }
            catch (SoapException ex)
            {
                Trace.TraceError("Error retrieving Pending SMS. {0} \n {1}", ex.Detail.InnerText, ex.StackTrace);
                throw;
            }
        }

        public void Update(CrmSms sms)
        {
            try
            {
                connection.CrmService.Update(sms.ToCrmDynamicEntity());
            }
            catch (SoapException ex)
            {
                Trace.TraceError("Error updating SMS. {0} \n {1}", ex.Detail.InnerText, ex.StackTrace);
                throw;
            }
        }

        public Guid Create(CrmSms sms)
        {
            if (sms.CrmContactId == Guid.Empty)
                sms.CrmContactId = FindContactByPhone(sms.MobilePhone);

            try
            {
                return connection.CrmService.Create(sms.ToCrmDynamicEntity());
            }
            catch (SoapException ex)
            {
                Trace.TraceError("Error creating  SMS. {0} \n {1}", ex.Detail.InnerText, ex.StackTrace);
                throw;
            }
        }

        public void UpdateParentSms(Guid parentSmsId, CrmSms response)
        {

            CrmSms parent = RetrieveCrmSmsById(parentSmsId);
            parent.CrmResponseId = response.CrmSmsId;
            response.CrmContactId = parent.CrmContactId;
            response.Subject = parent.Subject;

            try
            {
                connection.CrmService.Update(parent);
            }
            catch (SoapException ex)
            {
                Trace.TraceError("Error updating parent SMS {0}. {1} \n {2}", parent.CrmSmsId, ex.Detail.InnerText, ex.StackTrace);
                throw;
            }
            try
            {
                connection.CrmService.Update(response);
            }
            catch (SoapException ex)
            {
                Trace.TraceError("Error updating child SMS {0}. {1} \n {2}", response.CrmSmsId, ex.Detail.InnerText, ex.StackTrace);
                throw;
            }

        }

        private CrmSms RetrieveCrmSmsById(Guid crmSmsId)
        {
            RetrieveRequest request = new RetrieveRequest();
            request.ColumnSet = new ColumnSet(CrmSms.Columns);
            request.ReturnDynamicEntities = true;
            TargetRetrieveDynamic target = new TargetRetrieveDynamic();
            target.EntityName = CrmSms.SchemaName;
            target.EntityId = crmSmsId;
            request.Target = target;

            try
            {
                RetrieveResponse response = (RetrieveResponse)connection.CrmService.Execute(request);

                return new CrmSms((DynamicEntity)response.BusinessEntity);
            }
            catch (SoapException ex)
            {
                Trace.TraceError("Error retrieving SMS {0}. {1} \n {2}", crmSmsId , ex.Detail.InnerText, ex.StackTrace);
                throw;
            }
        }

        private Guid FindContactByPhone(string phone)
        {
            queryContact.Values = new object[] { phone };

            //Retrieve pending SMS from CRM
            RetrieveMultipleRequest request = new RetrieveMultipleRequest();
            request.Query = queryContact;
            request.ReturnDynamicEntities = true;

            try
            {
                RetrieveMultipleResponse response = (RetrieveMultipleResponse)connection.CrmService.Execute(request);

                if (response.BusinessEntityCollection.BusinessEntities.Count > 0)
                    return ((Key)((DynamicEntity)response.BusinessEntityCollection.BusinessEntities[0])["contactid"]).Value;
                else
                    return Guid.Empty;
            }
            catch (SoapException ex)
            {
                Trace.TraceError("Error trying to find contact for phone {0}. {1} \n {2}", phone, ex.Detail.InnerText, ex.StackTrace);
                throw;
            }
        }
    }
}
